package net.flyinggroup.gateway.config;

import net.flyinggroup.spring.gateway.security.oauth2.reactive.TokenRelayWithRefreshGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.client.oidc.web.server.logout.OidcClientInitiatedServerLogoutSuccessHandler;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
                                                            ReactiveClientRegistrationRepository clientRegistrationRepository) {
        return http
                // authenticate through oauth2/OpenID provider.
                .oauth2Login()
                .and()
                // logout the OpenID connect provider.
                .logout(customizer -> customizer.logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)))
                // protect all resources
                .authorizeExchange(customizer -> customizer.anyExchange().authenticated())
                // allow showing within a frame.
                .headers(customizer -> customizer.frameOptions().mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN))
                // disable CSRF to prevent conflicts with other proxied service CSRF.
                .csrf().disable()
                // build the chain.
                .build();
    }

    @Bean
    public TokenRelayWithRefreshGatewayFilterFactory tokenRelayWithRefreshGatewayFilterFactory(ServerOAuth2AuthorizedClientRepository authorizedClientRepository,
                                                                                               ReactiveClientRegistrationRepository clientRegistrationRepository) {
        return new TokenRelayWithRefreshGatewayFilterFactory(authorizedClientRepository, clientRegistrationRepository);
    }
}
